package cn.smile.commons.domain;

import cn.smile.bean.dto.core.SysUserDTO;
import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.exceptions.BusinessException;
import cn.smile.commons.response.MyResponseCode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

public abstract class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseDomain> extends ServiceImpl<M, T> implements IBaseService<T> {
    private static final String TABLE_FIELD_ID = "id";
    private static final String TABLE_FIELD_DEL = "is_deleted";

    @Override
    public boolean create(T domain) {
        this.addBaseCol(domain);
        return super.save(domain);
    }

    @Override
    public boolean update(T domain) {
        try {
            if (checkId(domain.getId())) {
                this.updateBaseCol(domain);
                return super.updateById(domain);
            }
            return false;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
    }

    @Override
    public boolean delById(String id) {
        T domain = this.get(id);
        if (Objects.isNull(domain)) {
            throw new BusinessException(MyResponseCode.RESULT_DATA_NONE);
        }
        this.delBaseCol(domain);

        return super.updateById(domain);
    }

    @Override
    public T get(String id) {
        T domain = baseMapper.selectOne(new QueryWrapper<T>().eq(TABLE_FIELD_ID, id).eq(TABLE_FIELD_DEL, Boolean.FALSE));
        if (Objects.isNull(domain)) {
            throw new BusinessException(MyResponseCode.RESULT_DATA_NONE);
        }
        return domain;
    }

    /**
     * 检查 ID 是否存在
     *
     * @param id {@code Long} ID
     * @return {@code boolean} ID 不存在则抛出异常
     */
    protected boolean checkId(String id) {
        if (!checkUniqueness(id)) {
            throw new BusinessException(MyResponseCode.RESULT_DATA_NONE);
        }
        return true;
    }

    protected boolean checkUniqueness(Object value) {
        QueryWrapper<T> qw = new QueryWrapper<>();
        qw.eq(TABLE_FIELD_ID, value);
        qw.eq(TABLE_FIELD_DEL, Boolean.FALSE);
        List<T> baseList = baseMapper.selectList(qw);
        return !CollectionUtils.isEmpty(baseList);
    }

    /**
     * 新增写入基本字段
     *
     * @param domain 对象
     */
    protected void addBaseCol(T domain) {
        domain.setDeleted(Boolean.FALSE);
        domain.setCreateTime(LocalDateTime.now());
        domain.setUpdateTime(LocalDateTime.now());
    }

    /**
     * 新增写入基本字段
     *
     * @param domain 对象
     */
    protected void updateBaseCol(T domain) {
        domain.setDeleted(Boolean.FALSE);
        domain.setUpdateTime(LocalDateTime.now());
    }

    /**
     * 新增写入基本字段
     *
     * @param domain 对象
     */
    protected void delBaseCol(T domain) {
        domain.setDeleted(Boolean.TRUE);
        domain.setUpdateTime(LocalDateTime.now());
    }

    /**
     * 用户列表转用户ID,昵称集合
     *
     * @param dataList 用户列表
     * @return Map<ID, 昵称>
     */
    protected Map<String, String> getUserMap(List<SysUserDTO> dataList) {
        Map<String, String> nickMap = new ConcurrentHashMap<>(NumberConstant.EIGHT);
        if (!CollectionUtils.isEmpty(dataList)) {
            dataList.forEach(dto -> nickMap.put(dto.getId(), dto.getNickName()));
        }
        return nickMap;
    }
}
